export default class RequireJS {
  //   private contexts: { [key: string]: any } = {};
  private modules: { [key: string]: any } = {};
  // 我们需要添加一个属性来存储exec方法传入的moduleName
  private lastExecModuleName: string | undefined;

  private currentModuleDefinition: {
    name?: string;
    factory: any;
    deps: any[];
  } | null = null;

  constructor() {
    // 初始化代码，如果需要的话
    // 在构造函数中定义 window.define
    //   if (typeof global.define !== "function") {
    //     global.define = this.define.bind(this);
    //     global.define.amd = {};
    //   }
  }

  public require(
    deps: string[],
    callback: (...deps: any[]) => void,
    errback?: (error: any) => void
  ): any {
    this.loadDependencies(deps, callback, errback);
  }

  public define(
    name: string,
    deps: string[],
    factory: (...deps: any[]) => any
  ): void {
    this.registerModule(name, deps, factory);
  }

  // public define(
  //   name: string | Function,
  //   deps: string[],
  //   factory: (...deps: any[]) => any
  // ): void {
  //   if (typeof name === "function") {
  //     // 如果是匿名模块定义，我们需要存储 factory 和 deps
  //     // 直到模块被加载时我们才能知道模块名
  //     this.currentModuleDefinition = {
  //       factory: name,
  //       deps: []
  //     };
  //   } else if (Array.isArray(name)) {
  //     const newFactory = deps as any;
  //     const newDeps = name as any[];

  //     // 如果是匿名模块定义，我们需要存储 factory 和 deps
  //     this.currentModuleDefinition = {
  //       factory: newFactory,
  //       deps: newDeps
  //     };
  //   } else {
  //     // 正常的模块定义
  //     const moduleName = this.lastExecModuleName;
  //     this.registerModule(moduleName ? moduleName : name, deps, factory);
  //   }
  // }

  public execDefine(
    define: (define: any, require?: any) => void,
    moduleName: string
  ): any {
    this.lastExecModuleName = moduleName; // 存储当前exec调用的moduleName
    define(this.define.bind(this), this.requireModule.bind(this));
    return this.requireModule(moduleName!);
  }

  public importModule = async (amdModuleName: string): Promise<any> => {
    return new Promise((resolve, reject) => {
      this.require(
        [amdModuleName],
        (amdModule: any) => {
          // console.log("amdModule", amdModule);
          // module = amdModule; // 调用模块导出的函数
          resolve(amdModule);
        },
        (err: any) => {
          // console.error("Error loading module:", err);
          console.log("Error loading module:", amdModuleName);
          reject(err);
        }
      );
    });
    // const exports = this.getModule(amdModuleName).exports;

    // return exports;
  };

  public requireModule = (amdModuleName: string): any => {
    const exports = this.getModule(amdModuleName)?.exports;
    return exports;
  };

  public has = (amdModuleName: string): boolean => {
    return !!this.modules[amdModuleName];
  };

  private loadDependencies(
    deps: string[],
    callback: (...deps: any[]) => void,
    errback?: (error: any) => void
  ): void {
    const modules: any[] = [];
    let remaining = deps.length;

    const onload = (dep: string, index: number) => {
      modules[index] = this.getModule(dep);
      remaining--;

      if (remaining === 0) {
        callback(modules[0].exports);
      }
    };

    deps.forEach((dep, index) => {
      this.loadModule(dep, onload.bind(this, dep, index), errback);
    });
  }

  private getModule(name: string): any {
    if (!this.modules[name]) {
      // throw new Error(`Module ${name} is not defined`);
      console.log(`Module ${name} is not defined`);
      return null;
    }
    return this.modules[name];
  }

  private loadModule(
    name: string,
    callback: () => void,
    errback?: (error: any) => void
  ): void {
    name;
    errback;
    // 这里应该是加载模块的逻辑，可能是异步的，例如从服务器获取
    // 为了简化，我们假设模块已经定义好了，直接调用回调
    callback();
  }

  private registerModule(
    name: string,
    deps: string[],
    factory: (...deps: any[]) => any
  ): void {
    this.modules[name] = {
      deps,
      factory,
      exports: {}
    };

    // 这里应该是执行模块工厂函数的逻辑，并保存模块的导出
    // 为了简化，我们假设模块的导出是工厂函数的返回值
    const module = this.modules[name];
    const moduleDeps = deps.map((dep) => {
      if (dep === "require") {
        return (depName: string) => this.getModule(depName).exports;
      } else if (dep === "exports") {
        return module.exports; // 使用模块的 exports 对象
      } else if (dep === "module") {
        return module; // 使用模块的 exports 对象
      } else {
        return this.getModule(dep).exports;
      }
    });
    const factoryResult = factory.apply(null, moduleDeps);
    // console.log(name,factoryResult)
    // 如果工厂函数返回了一个值，那么它将成为模块的导出
    module.exports = factoryResult || module.exports;
  }
}
